/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Data.Objects.DataClasses;
#if _LOCALDB
  using Oceanside.LocalDB;
#else
using Oceanside.RemoteDB;
#endif
namespace Oceanside
{
    static class POBindings
    {
        ///This is needed for when we drop in and out of modifier mode.
        private static int _previouslySelectedMainPivotIndex = 0;

        private static int _mainPivotIndex = 0;
        private static int _subPivotIndex = 0;
        private static int _seatPivotIndex = 0;
        private static int _selectedSeatIndex = 0;

        public static int SelectedSeatIndex
        {
            get
            {
                if (Constants.IsQuickServiceMode)
                {
                    return 0;
                }
                else
                {
                    return POBindings._selectedSeatIndex;
                }
            }
            set { POBindings._selectedSeatIndex = value; }
        }
        private static int _previousSeatIndex = 0;


        private static int _custTicketScrollIndex = -1;

        private static Brush _exitModifierModeTextBrush;
        private static Brush _modifierHotKeysBrush;
        private static Brush _normalModifierTextBrush;

        /// <summary>
        /// 
        /// </summary>
        private static String _buttonEightOriginalText = "";
        private static String _buttonAux2_OriginalText = "";
        private static String _buttonAux3_OriginalText = "";
        private static String _buttonAux4_OriginalText = "";

        private static String _exceptionModPrinterNote = "";

        private static List<MainMenuButton_155_58> _mainCategoryButtonsList = null;
        private static List<FlatButton_155_58> _subCategoryButtonsList = null;
        private static List<FlatButton_52_58> _seatButtonsList = null;

        private static PRODUCT _selectedProduct = null;
        private static EXCEPTION_MODIFIER_GROUP _selectedExceptionModifierGroup = null;
        private static EXCEPTION_MODIFIER _selectedExceptionModifier = null;
        private static FORCED_MODIFIER_GROUP _selectedForcedModifierGroup = null;
        private static FORCED_MODIFIER _selectedForcedModifier = null;
        private static PRODUCT_GROUP[] _productGroupsList = null;
        private static PRODUCT[] _productsForProductGroupList = null;

        private static FORCED_MODIFIER_GROUP[] _forcedModifierGroupsList = null;
        private static FORCED_MODIFIER[] _forcedModifiersForForcedGroupList = null;

        private static EXCEPTION_MODIFIER_GROUP[] _exceptionModifierGroupsList = null;
        private static EXCEPTION_MODIFIER[] _exceptionModifiersForExceptionGroupList = null;


        private static SALE _selectedSale = null;
        public static SALE SelectedSale
        {
            get { return POBindings._selectedSale; }
            set { POBindings._selectedSale = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public enum OrderMode
        {
            EXCEPTIONMOD_MODE,
            FORCEDMOD_MODE,
            PRODUCT_MODE
        }

        /// <summary>
        /// Keep track of what mode this page is in.
        /// </summary>
        private static OrderMode _currentFormMode = OrderMode.PRODUCT_MODE;
        public static OrderMode CurrentFormMode
        {
            get { return POBindings._currentFormMode; }
            set { POBindings._currentFormMode = value; }
        }


        /// <summary>
        /// Constructor
        /// </summary>
        public static void Init()
        {
            _exitModifierModeTextBrush = new SolidColorBrush(Color.FromRgb(0x47, 0xF1, 0xF2));
            _exitModifierModeTextBrush.Freeze();

            _modifierHotKeysBrush = new SolidColorBrush(Color.FromRgb(0xB9, 0x07, 0x07));
            _modifierHotKeysBrush.Freeze();

            WrapPanel wp = Oceanside.OrderApi.PanelTopFunctions;

            _normalModifierTextBrush = (wp.Children[7] as Button_95_50).ButtonBackground;
            _normalModifierTextBrush.Freeze();
            _seatButtonsList = new List<FlatButton_52_58>(4);
            _seatButtonsList.Add(Oceanside.OrderApi.SeatPosition1);
            _seatButtonsList.Add(Oceanside.OrderApi.SeatPosition2);
            _seatButtonsList.Add(Oceanside.OrderApi.SeatPosition3);
            _seatButtonsList.Add(Oceanside.OrderApi.SeatPosition4);

            ///Make sure to update the ticket index when it is clicked.
            Oceanside.OrderApi.CustomerTicketListView.SelectionChanged +=
                new SelectionChangedEventHandler(CustomerTicketListView_SelectionChanged);

            ///Load the array of main buttons
            _mainCategoryButtonsList =
                new List<Oceanside.MainMenuButton_155_58>(Constants.CONST_ROWS_PER_VIEW);

            StackPanel sp = Oceanside.OrderApi.MainMenuStack;

            foreach (object o in sp.Children)
            {
                _mainCategoryButtonsList.Add(o as MainMenuButton_155_58);
            }

            ///Load the array of sub buttons
            _subCategoryButtonsList = new List<Oceanside.FlatButton_155_58>(Constants.CONST_BUTTN_PER_SUBVIEW);
            WrapPanel wpsub = Oceanside.OrderApi.SubMenuWrap;

            foreach (object o in wpsub.Children)
            {
                _subCategoryButtonsList.Add(o as FlatButton_155_58);
            }

            ///Set the event handlers
            Oceanside.OrderApi.ScrollMainMenuUPButton.ShineButtonClicked +=
                new RoutedEventHandler(buttonMainScrollUp_ShineButtonClicked_NOTHROW);
            Oceanside.OrderApi.ScrollMainMenuDownButton.ShineButtonClicked +=
                new RoutedEventHandler(buttonMainScrollDown_ShineButtonClicked_NOTHROW);
            Oceanside.OrderApi.ScollSubMenuUpButton.ShineButtonClicked +=
                new RoutedEventHandler(buttonSubmenuUp_Click_NOTHROW);
            Oceanside.OrderApi.ScollSubMenuDownButton.ShineButtonClicked +=
                new RoutedEventHandler(buttonSubmenuDown_Click_NOTHROW);
            Oceanside.OrderApi.ScrollSeatLeft.OnFlatButtonClicked +=
                new RoutedEventHandler(buttonScrollSeatLeft_Click_NOTHROW);
            Oceanside.OrderApi.ScrollSeatRight.OnFlatButtonClicked +=
                new RoutedEventHandler(buttonScrollSeatRight_Click_NOTHROW);

            ///Wire in the event handlers for the seat position buttons.
            Oceanside.OrderApi.SeatPosition1.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            Oceanside.OrderApi.SeatPosition2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            Oceanside.OrderApi.SeatPosition3.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            Oceanside.OrderApi.SeatPosition4.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);

            foreach (Oceanside.MainMenuButton_155_58 sb in _mainCategoryButtonsList)
            {
                sb.ShineButtonClicked += new RoutedEventHandler(sb_mainMenuButtonClicked_NOTHROW);
            }

            foreach (FlatButton_155_58 fb in _subCategoryButtonsList)
            {
                fb.ButtonClicked += new RoutedEventHandler(buttonSubMenu_Click_NOTHROW);
            }

            SetMainCatDataContext();
            SetSubCatDataContext();

            Constants.MenuIsInitialized = true;
        }


        static void CustomerTicketListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                int idx = (sender as ListView).SelectedIndex;

                ///Make sure this does not return a negative numTimes.  When we are in the middle
                ///of processing an event after a delete, this selected index change event will
                ///fire even though we have not updated the selected index yet.
                if (idx >= 0)
                {
                    _custTicketScrollIndex = idx;
                    _selectedSale = Oceanside.OrderApi.CustomerTicketListView.Items[idx] as SALE;
                    if (_selectedSale != null)
                    {
                        if (_selectedSale.IsExceptionModifier)
                        {
                            _selectedExceptionModifierGroup =
                                SHIFT.GlobalContext.EXCEPTION_MODIFIER_GROUPS.
                                Where(g => g.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();

                            _selectedExceptionModifier = SHIFT.GlobalContext.EXCEPTION_MODIFIERS
                                .Where(g => g.Id == _selectedSale.ProductId).FirstOrDefault();
                        }
                        else if (_selectedSale.IsForcedModifier)
                        {
                            _selectedForcedModifierGroup =
                                SHIFT.GlobalContext.FORCED_MODIFIER_GROUPS.
                                Where(g => g.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();

                            _selectedForcedModifier = SHIFT.GlobalContext.FORCED_MODIFIERS
                                .Where(g => g.Id == _selectedSale.ProductId).FirstOrDefault();
                        }
                        else
                        {
                            MainMenuButton_155_58.SelectedProductGroup = SHIFT.GlobalContext.PRODUCT_GROUPS
                                .Where(g => g.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();

                            _selectedProduct = SHIFT.GlobalContext.PRODUCTS
                                .Where(g => g.Id == _selectedSale.ProductId).FirstOrDefault();
                        }
                    }
                }
                else
                {
                    _selectedSale = null;
                }
                if (Constants.IsQuickServiceMode)
                {
                    CCBindings.SelectedSeatIndex = 0;
                    OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                    OrderApi.CustomerCheckListView.Items.Refresh();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_CUST_TICKET_SELECTION_CHANGED, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void MenuChanged_NOTHROW()
        {
            try
            {
                Constants.MenuIsInitialized = false;

                ///If we are changing the menu, make sure we are not in in a modifier mode first
                ///by exiting from mod mode.
                CheckExitMod();

                ///This is needed for when we drop in and out of modifier mode.
                _previouslySelectedMainPivotIndex = 0;
                _mainPivotIndex = 0;
                _subPivotIndex = 0;
                _seatPivotIndex = 0;
                SelectedSeatIndex = 0;
                _selectedProduct = null;
                MainMenuButton_155_58.SelectedProductGroup = null;
                _selectedExceptionModifier = null;
                _selectedExceptionModifierGroup = null;
                Oceanside.MainMenuButton_155_58.UnHighLightCurrent();
                SetMainCatDataContext();
                SetSubCatDataContext();

                Constants.MenuIsInitialized = true;
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_MENU_CHANGED, exc);
            }
        }

        public static void PrepareForScreenLeave_NOTHROW()
        {
            if (Constants.IsQuickServiceMode)
            {
                ORDER lastOrder = SHIFT.Current.ORDERS.OrderByDescending(o => o.Id).FirstOrDefault();

                if (lastOrder != null && SHIFT.SelectedOrder != null)
                {
                    bool isLastOrder = SHIFT.SelectedOrder.Id == lastOrder.Id;

                    if (lastOrder.CanDeleteOrder())
                    {
                        SHIFT.RemoveOrder(lastOrder);

                        if (isLastOrder)
                        {
                            if (SHIFT.Current.ORDERS.Any())
                            {
                                SHIFT.SelectedOrder = SHIFT.Current.ORDERS.OrderByDescending(o => o.Id).FirstOrDefault();
                            }
                            else
                            {
                                SHIFT.SelectedOrder = null;
                            }
                        }
                    }
                }
                ClearSeatsDataContext();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void PrepareForScreenChange_NOTHROW()
        {
            try
            {
                if (OrderApi.ShowGridMessage)
                {
                    Oceanside.OrderApi.GridModifyMessage.Visibility = Visibility.Visible;
                    OrderApi.ShowGridMessage = false;
                }
                else
                {
                    Oceanside.OrderApi.GridModifyMessage.Visibility = Visibility.Hidden;
                }
                MainMenuButton_155_58.SelectedProductGroup = null;
                _selectedProduct = null;
                _selectedSale = null;
                _selectedExceptionModifier = null;
                _selectedExceptionModifierGroup = null;
                _selectedForcedModifier = null;
                _selectedForcedModifierGroup = null;
                ResetMenuPivotIndices();

                SetMainCatDataContext();

                bool foundDefault = false;
                if (Constants.IsQuickServiceMode && MENU.CachedMenu.DefaultSelectedProductGroupId != null)
                {
                    if (_productGroupsList != null && _productGroupsList.Count() != 0)
                    {
                        for (int i = 0; (i < _productGroupsList.Count() && !foundDefault); i++)
                        {
                            Int64 defaultId = (Int64)MENU.CachedMenu.DefaultSelectedProductGroupId;
                            if (_productGroupsList[i].Id == defaultId)
                            {
                                MainMenuButtonClicked(i);
                                foreach (MainMenuButton_155_58 b in _mainCategoryButtonsList)
                                {
                                    PRODUCT_GROUP pg = b.DataContext as PRODUCT_GROUP;
                                    if (pg != null)
                                    {
                                        if (pg.Id == defaultId)
                                        {
                                            b.HighlightNew();
                                            foundDefault = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                if (!foundDefault)
                {
                    MainMenuButtonClicked(0);
                    MainMenuButton_155_58.FirstButton.HighlightNew();
                }

                SetSubCatDataContext();
                _exceptionModPrinterNote = "";
                _seatPivotIndex = 0;

                if (Constants.IsQuickServiceMode)
                {
                    _seatPivotIndex = SHIFT.Current.ORDERS.Count - SHIFT.SelectedOrder.TableInt;
                    _previousSeatIndex = _seatPivotIndex;
                }
                SetSeatTags(_seatPivotIndex);
                SwitchOrder(SHIFT.SelectedOrder);
                CustomerTicketListView_SelectionChanged(OrderApi.CustomerTicketListView, null);
                if (Constants.IsQuickServiceMode)
                {
                    CCBindings.SelectedSeatIndex = 0;
                    OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                    OrderApi.CustomerCheckListView.Items.Refresh();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_PREPARE_FOR_SCREEN_CHANGE, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static String TableDisplayString
        {
            get { return Oceanside.OrderApi.TableNumberLabel.Content as String; }
            set { Oceanside.OrderApi.TableNumberLabel.Content = value; }
        }

        /// <summary>
        /// Used to set the card holders name to their table.
        /// </summary>
        /// <param name="cardHolderName"></param>
        public static void SetHeadOfTable(String cardHolderName, bool showDialog = true)
        {
            SHIFT.SelectedOrder.HasHeadOfTable = true;
            ///Things will be an overflow mess if we let the length go over 20.  As such, be safer at 19.
            if (cardHolderName.Length > 19)
            {
                SHIFT.SelectedOrder.CustomerName = cardHolderName.Substring(0, 19);
                SHIFT.SelectedOrder.CustomerName = SHIFT.SelectedOrder.CustomerName.Trim();
            }
            else
            {
                SHIFT.SelectedOrder.CustomerName = cardHolderName;
            }

            if (showDialog)
            {
                if (string.IsNullOrEmpty(SHIFT.SelectedOrder.CustomerName))
                {
                    if (SYSCONFIG.Get(SHIFT.GlobalContext).AllowCardOnFile)
                    {
                        UMD.ShowGuiMessageSTASafe_NOTHROW("The card has been set for the head of the table; however the name of the cardholder could not be determined.  This can happen if the card is a prepaid card or the entire contents of the card could not be read correctly.");
                    }
                }
                else
                {
                    UMD.ShowGuiMessageSTASafe_NOTHROW(SHIFT.SelectedOrder.CustomerName + " is now the head of table #" + SHIFT.SelectedOrder.TableNumber + ".");
                }
            }
        }

        /// <summary>
        /// Used to customerCheck to see if we can modify the EfProductObject.
        /// </summary>
        /// <param Name="EfProductObject"></param>
        public static Boolean CanModifyProduct(SALE product)
        {
            ///If the EfProductObject is not pending then it has already been placed for order.
            if (product.CountPendingKitchenSend == 0)
            {
                UMD.ShowGuiMessageSTASafe_NOTHROW("You cannot modify a product that has already been submitted for order.");
            }
            return product.CountPendingKitchenSend != 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonMainScrollUp_ShineButtonClicked_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                ///If there is more pivot room.
                if (_mainPivotIndex > 0)
                {
                    ///If there is an entire panels worth of pivot
                    if ((_mainPivotIndex - Constants.CONST_ROWS_PER_VIEW) >= 0)
                    {
                        _mainPivotIndex -= Constants.CONST_ROWS_PER_VIEW;
                    }
                    else ///Its greater than zero, but not a panels worth. Set to zero.
                    {
                        _mainPivotIndex = 0;
                    }

                    ///Remove the highlight from the main menu button because we are scrolling up a pivot and it will give the false
                    ///impression that the wrong category is selected.
                    Oceanside.MainMenuButton_155_58.UnHighLightCurrent();
                    SetMainCatDataContext();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_MAIN_MENU_SCROLL_UP, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void sb_mainMenuButtonClicked_NOTHROW(object sender, RoutedEventArgs e)
        {
            try
            {
                e.Handled = true;
                string indxString = (string)((Oceanside.MainMenuButton_155_58)e.OriginalSource).Tag;
                int selectedIndex = Convert.ToInt32(indxString);
                MainMenuButtonClicked(selectedIndex);
                SetSubCatDataContext();
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_MAIN_MENU_BUTTON_CLICKED, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private static void MainMenuButtonClicked(int selectedIndex)
        {
            _subPivotIndex = 0;
            if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
            {
                _selectedForcedModifierGroup = _forcedModifierGroupsList[selectedIndex];
                if (_selectedForcedModifierGroup != null && _selectedProduct != null)
                {
                    Oceanside.OrderApi.TbModifyMessage.Text = _selectedProduct.GetModifierChoiceInstruction(_selectedForcedModifierGroup);
                }
            }
            else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
            {
                _selectedExceptionModifierGroup = _exceptionModifierGroupsList[selectedIndex];
            }
            else
            {
                MainMenuButton_155_58.SelectedProductGroup = _productGroupsList[selectedIndex];
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param Name="table"></param>
        private static void SwitchOrder(ORDER table)
        {
            SHIFT.SelectedOrder = table;
            OrderApi.OrderBorder.DataContext = table;
            SeatChangeOccured(0);
            SetScrollableSeatButtonsDataContext();
        }


        /// <summary>
        /// This function is called when a seat scroll, addition or button click has
        /// caused an event.
        /// </summary>
        /// <param Name="newIndex"></param>
        public static void SeatChangeOccured(int newIndex)
        {
            try
            {
                if (Constants.IsQuickServiceMode)
                {
                    ///Reset the line items scroll index on the customer ticket since we are
                    ///switching to a different seat.
                    _custTicketScrollIndex = 0;
                    _selectedSale = null;
                    UpdateTicketFocus();
                }
                else
                {
                    ///Update the selected index and selected seat, but first assure it is in bounds.
                    if (newIndex >= 0 && newIndex < SHIFT.SelectedOrder.GuestCount)
                    {
                        ///Reset the line items scroll index on the customer ticket since we are
                        ///switching to a different seat.
                        _custTicketScrollIndex = 0;

                        ///Update the selected seat index.
                        SelectedSeatIndex = newIndex;
                        _selectedSale = null;
                        UpdateTicketFocus();
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private static void SetSeatTags(int pivot)
        {
            if (Constants.IsQuickServiceMode)
            {
                List<ORDER> fourOrdersList = null;
                if (SHIFT.Current.ORDERS.Count >= 4)
                {
                    if ((SHIFT.Current.ORDERS.Count - pivot) < 4)
                    {
                        fourOrdersList = SHIFT.Current.ORDERS.OrderByDescending(o => o.Id).Skip(SHIFT.Current.ORDERS.Count - 4).Take(4).ToList();
                    }
                    else
                    {
                        fourOrdersList = SHIFT.Current.ORDERS.OrderByDescending(o => o.Id).Skip(pivot).Take(4).ToList();
                    }

                    ///Now we need to reorder ascending.
                    fourOrdersList = fourOrdersList.OrderBy(o => o.Id).ToList();
                }
                else
                {
                    fourOrdersList = SHIFT.Current.ORDERS.ToList();
                }

                for (int i = 0; i < _seatButtonsList.Count; i++)
                {
                    FlatButton_52_58 s = _seatButtonsList[i];
                    if (i > (fourOrdersList.Count - 1))
                    {
                        s.LabelNumber = 0;
                        s.LabelString = null;
                        s.DataContext = null;
                    }
                    else
                    {
                        s.LabelNumber = fourOrdersList[i].TableInt;
                        s.LabelString = "Order\n" + s.LabelNumber;
                        s.DataContext = fourOrdersList[i];
                    }
                }
            }
            else
            {
                int i = SHIFT.SelectedOrder.GuestCount - SelectedSeatIndex;
                int numBlanks = Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA - i;

                int seatNumber = (SelectedSeatIndex + 1);
                if (SHIFT.SelectedOrder.GuestCount <= Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                {
                    seatNumber = 1;
                }
                else if (numBlanks > 0)
                {
                    seatNumber = seatNumber - numBlanks;
                }

                foreach (FlatButton_52_58 s in _seatButtonsList)
                {
                    if (seatNumber > SHIFT.SelectedOrder.GuestCount)
                    {
                        s.LabelNumber = 0;
                        s.LabelString = null;
                    }
                    else
                    {
                        s.LabelNumber = seatNumber;
                        s.LabelString = "Seat\n" + seatNumber;
                        seatNumber += 1;
                    }
                }
            }
        }

        /// <summary>
        /// Handles when a seat itself has been clicked rather than a scroller.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSeat_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            if (!POBindings.IsPendingAction())
            {
                try
                {
                    Oceanside.FlatButton_52_58 b = (Oceanside.FlatButton_52_58)e.Source;

                    if (null != b)
                    {
                        int zeroBasedIndx = b.LabelNumber - 1;
                        if (Constants.IsQuickServiceMode)
                        {
                            ORDER o = b.DataContext as ORDER;
                            if (o != null)
                            {
                                if (o.Id != SHIFT.SelectedOrder.Id)
                                {
                                    SHIFT.SelectedOrder = o;
                                    _seatPivotIndex = SHIFT.Current.ORDERS.Count - (zeroBasedIndx + 1);
                                    QuickServiceSwitchOrder(_previousSeatIndex);
                                }
                            }
                        }
                        else
                        {
                            if (zeroBasedIndx < SHIFT.SelectedOrder.GuestCount && zeroBasedIndx >= 0)
                            {
                                SeatChangeOccured(zeroBasedIndx);
                                foreach (FlatButton_52_58 seat in _seatButtonsList)
                                {
                                    seat.Unselect();
                                }
                                b.Select();
                                SetScrollableSeatButtonsDataContext(false);
                            }
                        }
                    }
                }
                catch (Exception exc)
                {
                    Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SEAT_BUTTON_CLICK, exc);
                }
            }
        }

        /// <summary>
        /// Will scroll the seats to the right if possible
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatRight_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            if (!POBindings.IsPendingAction())
            {
                try
                {
                    e.Handled = true;

                    if (Constants.IsQuickServiceMode)
                    {
                        if (_seatPivotIndex != 0)
                        {
                            if (_seatPivotIndex > 0)
                            {
                                _seatPivotIndex -= 1;
                                _previousSeatIndex = _seatPivotIndex;
                            }
                            SHIFT.SelectedOrder = SHIFT.Current.ORDERS.OrderByDescending(o => o.Id).Skip(_seatPivotIndex).First();
                            QuickServiceSwitchOrder();
                        }
                    }
                    else
                    {
                        int seatCount = SHIFT.SelectedOrder.GuestCount;
                        if (SelectedSeatIndex != (seatCount - 1))
                        {
                            if ((seatCount - _seatPivotIndex) > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                            {
                                _seatPivotIndex += 1;
                            }
                            SeatChangeOccured(SelectedSeatIndex + 1);
                            SetSeatTags(_seatPivotIndex);
                            SetScrollableSeatButtonsDataContext();
                        }
                    }
                }
                catch (Exception exc)
                {
                    Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_RIGHT, exc);
                }
            }
        }

        private static void QuickServiceSwitchOrder(int previousPivot = -10)
        {
            POBindings.TableDisplayString = "Order " + SHIFT.SelectedOrder.TableInt;
            _selectedProduct = null;
            _selectedSale = null;
            _selectedExceptionModifier = null;
            _selectedExceptionModifierGroup = null;
            _selectedForcedModifier = null;
            _selectedForcedModifierGroup = null;
            SetMainCatDataContext();
            SetSubCatDataContext();

            if (previousPivot != -10)
            {
                SetSeatTags(previousPivot);
            }
            else
            {
                SetSeatTags(_seatPivotIndex);
            }
            _exceptionModPrinterNote = "";
            SetScrollableSeatButtonsDataContext();
            CustomerTicketListView_SelectionChanged(OrderApi.CustomerTicketListView, null);
            OrderApi.OrderBorder.DataContext = SHIFT.SelectedOrder;
            if (Constants.IsQuickServiceMode)
            {
                CCBindings.SelectedSeatIndex = 0;
                OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                OrderApi.CustomerCheckListView.Items.Refresh();
            }
            PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
        }

        /// <summary>
        /// Scroll the seats to the left if possible.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatLeft_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            if (!POBindings.IsPendingAction())
            {
                try
                {
                    if (Constants.IsQuickServiceMode)
                    {
                        int orderCount = SHIFT.Current.ORDERS.Count;
                        if ((orderCount - _seatPivotIndex) > 1)
                        {
                            _seatPivotIndex += 1;
                            _previousSeatIndex = _seatPivotIndex;
                            SHIFT.SelectedOrder = SHIFT.Current.ORDERS.OrderByDescending(o => o.Id).Skip(_seatPivotIndex).First();
                            QuickServiceSwitchOrder();
                        }
                    }
                    else
                    {
                        if (SelectedSeatIndex != 0)
                        {
                            if ((SelectedSeatIndex - _seatPivotIndex) == 0)
                            {
                                _seatPivotIndex--;
                            }
                            SeatChangeOccured(SelectedSeatIndex - 1);
                            SetSeatTags(_seatPivotIndex);
                            SetScrollableSeatButtonsDataContext();
                        }
                    }
                }
                catch (Exception exc)
                {
                    Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_LEFT, exc);
                }
            }
        }

        /// <summary>
        /// Used to update the data Context of the main category panel.  It could be either main mod mode
        /// or just main EfProductObject group mode.
        /// </summary>
        private static void SetMainCatDataContext()
        {
            int count = 0;
            if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
            {
                _forcedModifierGroupsList = MENU.GetForcedModifierGroupsInView(_selectedProduct, _mainPivotIndex);

                if (null != _forcedModifierGroupsList)
                {
                    count = _forcedModifierGroupsList.Length;
                }
            }
            else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
            {
                _exceptionModifierGroupsList = MENU.GetExceptionModifierGroupsInView(MainMenuButton_155_58.SelectedProductGroup, _mainPivotIndex);

                if (null != _exceptionModifierGroupsList)
                {
                    count = _exceptionModifierGroupsList.Length;
                }
            }
            else
            {
                _productGroupsList = MENU.GetMainCategories(_mainPivotIndex);

                if (null != _productGroupsList)
                {
                    count = _productGroupsList.Length;
                }
            }

            for (int indx = 0; indx < Constants.CONST_ROWS_PER_VIEW; indx++)
            {
                if (count > indx)
                {
                    _mainCategoryButtonsList[indx].Visibility = Visibility.Visible;

                    if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
                    {
                        _mainCategoryButtonsList[indx].DataContext = _forcedModifierGroupsList[indx];
                    }
                    else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
                    {
                        _mainCategoryButtonsList[indx].DataContext = _exceptionModifierGroupsList[indx];
                    }
                    else
                    {
                        _mainCategoryButtonsList[indx].DataContext = _productGroupsList[indx];
                    }
                }
                else
                {
                    _mainCategoryButtonsList[indx].Visibility = Visibility.Hidden;
                }
            }
        }

        /// <summary>
        /// Used to set the correct data Context for the submenu.  It may be either modifier mode or
        /// just normal select a EfProductObject mode.
        /// </summary>
        private static void SetSubCatDataContext()
        {
            int count = 0;
            if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
            {
                _forcedModifiersForForcedGroupList = MENU.GetForcedModifiersInView(_selectedForcedModifierGroup, _subPivotIndex);
                if (_forcedModifiersForForcedGroupList != null)
                {
                    count = _forcedModifiersForForcedGroupList.Length;
                }
            }
            else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
            {
                _exceptionModifiersForExceptionGroupList =
                    MENU.GetExceptionModifiersInView(_selectedExceptionModifierGroup, _subPivotIndex);
                if (_exceptionModifiersForExceptionGroupList != null)
                {
                    count = _exceptionModifiersForExceptionGroupList.Length;
                }
            }
            else
            {
                _productsForProductGroupList = MENU.GetProductsInView(MainMenuButton_155_58.SelectedProductGroup, _subPivotIndex);

                if (_productsForProductGroupList != null)
                {
                    count = _productsForProductGroupList.Length;
                }
            }

            for (int indx = 0; indx < Constants.CONST_BUTTN_PER_SUBVIEW; indx++)
            {
                if (count > indx)
                {
                    _subCategoryButtonsList[indx].Visibility = Visibility.Visible;

                    if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
                    {
                        _subCategoryButtonsList[indx].DataContext = _forcedModifiersForForcedGroupList[indx];
                    }
                    else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
                    {
                        _subCategoryButtonsList[indx].DataContext = _exceptionModifiersForExceptionGroupList[indx];
                    }
                    else
                    {
                        _subCategoryButtonsList[indx].DataContext = _productsForProductGroupList[indx];
                    }
                }
                else
                {
                    _subCategoryButtonsList[indx].Visibility = Visibility.Hidden;
                }
            }
        }

        private static void ClearSeatsDataContext()
        {
            for (int indx = 0; indx < Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA; indx++)
            {
                ORDER seatsOrder = _seatButtonsList[indx].DataContext as ORDER;
                if (seatsOrder != null)
                {
                    _seatButtonsList[indx].Unselect();
                    _seatButtonsList[indx].DataContext = null;
                }
            }
        }

        /// <summary>
        /// This function assures that the scrollable seats display correctly.
        /// </summary>
        public static void SetScrollableSeatButtonsDataContext(bool updateSelction = true)
        {
            try
            {
                if (Constants.IsQuickServiceMode)
                {
                    OrderApi.CustomerTicketListView.DataContext = SHIFT.SelectedOrder.GetSeatsSales(SelectedSeatIndex);

                    if (updateSelction)
                    {
                        for (int indx = 0; indx < Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA; indx++)
                        {
                            ORDER seatsOrder = _seatButtonsList[indx].DataContext as ORDER;
                            if (seatsOrder != null)
                            {
                                if (seatsOrder.Id == SHIFT.SelectedOrder.Id)
                                {
                                    _seatButtonsList[indx].Select();
                                }
                                else
                                {
                                    _seatButtonsList[indx].Unselect();
                                }
                            }
                        }
                    }
                }
                else
                {
                    OrderApi.CustomerTicketListView.DataContext = SHIFT.SelectedOrder.GetSeatsSales(SelectedSeatIndex);

                    if (updateSelction)
                    {
                        for (int indx = 0; indx < Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA; indx++)
                        {
                            if (indx == (SelectedSeatIndex - _seatPivotIndex))
                            {
                                _seatButtonsList[indx].Select();
                            }
                            else
                            {
                                _seatButtonsList[indx].Unselect();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
        }


        /// <summary>
        /// Should be called whenever we delete an item from the customer ticket or
        /// add or scroll items.
        /// </summary>
        public static void UpdateTicketFocus(bool focusLastItem = false)
        {
            List<SALE> sales = SHIFT.SelectedOrder.GetSeatsSales(SelectedSeatIndex).ToList();

            Oceanside.OrderApi.CustomerTicketListView.DataContext = sales;
            OrderApi.CustomerTicketListView.Items.Refresh();

            if (Constants.IsQuickServiceMode)
            {
                CCBindings.SelectedSeatIndex = 0;
                OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                OrderApi.CustomerCheckListView.Items.Refresh();
            }

            if (_custTicketScrollIndex >= sales.Count || focusLastItem)
            {
                _custTicketScrollIndex = sales.Count - 1;
                if (_custTicketScrollIndex < 0)
                {
                    _custTicketScrollIndex = 0;
                }
            }

            if (sales.Count != 0)
            {
                SALE selSale = sales[_custTicketScrollIndex];
                Oceanside.OrderApi.CustomerTicketListView.SelectedItem = selSale;
                OrderApi.CustomerTicketListView.UpdateLayout();
                OrderApi.CustomerTicketListView.ScrollIntoView(selSale);
            }
        }

        /// <summary>
        /// Used to scroll the submenu / submod window downward.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSubmenuDown_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                bool shouldProcess = false;
                int lastIndex = 0;

                if (_currentFormMode == OrderMode.PRODUCT_MODE && MainMenuButton_155_58.SelectedProductGroup != null)
                {
                    shouldProcess = true;
                    lastIndex = MENU.GetSubCategoryCount(MainMenuButton_155_58.SelectedProductGroup);
                }
                else
                {
                    if (_selectedExceptionModifierGroup != null)
                    {
                        shouldProcess = true;
                        lastIndex = _selectedExceptionModifierGroup.EXCEPTION_MODIFIERS.Count;
                    }
                }

                if (shouldProcess && (lastIndex > (_subPivotIndex + Constants.CONST_BUTTN_PER_SUBVIEW)))
                {
                    _subPivotIndex += Constants.CONST_BUTTN_PER_SUBVIEW;
                    SetSubCatDataContext();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SUB_MENU_SCROLL_DOWN, exc);
            }
        }

        /// <summary>
        /// Used to scroll the submenu / submod window upward.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSubmenuUp_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                ///If there is more pivot room.
                if (_subPivotIndex > 0)
                {
                    ///If there is an entire panels worth of pivot
                    if ((_subPivotIndex - Constants.CONST_BUTTN_PER_SUBVIEW) >= 0)
                    {
                        _subPivotIndex -= Constants.CONST_BUTTN_PER_SUBVIEW;
                    }
                    else ///Its greater than zero, but not a panels worth. Set to zero.
                    {
                        _subPivotIndex = 0;
                    }
                    SetSubCatDataContext();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SUB_MENU_SCROLL_UP, exc);
            }
        }

        /// <summary>
        /// Used to scroll the main menu or main modifiers downward.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonMainScrollDown_ShineButtonClicked_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                int lastIndex = 0;

                if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
                {
                    lastIndex = MENU.GetForcedModifierGroupCount(_selectedProduct);
                }
                else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
                {
                    lastIndex = MainMenuButton_155_58.SelectedProductGroup.EXCEPTION_MODIFIER_GROUPS.Count;
                }
                else
                {
                    lastIndex = MENU.GetMainCategoryCount();
                }

                if (lastIndex > (_mainPivotIndex + Constants.CONST_ROWS_PER_VIEW))
                {
                    _mainPivotIndex += Constants.CONST_ROWS_PER_VIEW;

                    ///Remove the highlight from the main menu button because we are scrolling down a pivot and it will give the false
                    ///impression that the wrong category is selected.
                    Oceanside.MainMenuButton_155_58.UnHighLightCurrent();
                    SetMainCatDataContext();
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_MAIN_MENU_SCROLL_DOWN, exc);
            }
        }

        /// <summary>
        /// Reset these pivots as they are shared by the modifier mode and the normal mode
        /// of ordering.
        /// </summary>
        public static void ResetMenuPivotIndices()
        {
            _mainPivotIndex = 0;
            _subPivotIndex = 0;
        }


        /// <summary>
        /// 
        /// </summary>
        private static void DropIntoModifyMode(OrderMode mode)
        {
            if (_currentFormMode == OrderMode.PRODUCT_MODE)
            {
                if (_selectedSale != null && !(mode == OrderMode.EXCEPTIONMOD_MODE && !(_selectedSale.CountPendingKitchenSend > 0)))
                {
                    ///----------------------------------------------------------------
                    /// CAUTION: The order of all function calls in this function are 
                    /// very important.  If any code is added in this function, assure
                    /// you do not re-arrange or move things around without first 
                    /// making sure you are not breaking another piece of code.
                    /// For example, you must save the main index before performing an
                    /// index reset.  You must set the main category data Context
                    /// before trying to grab the selected modifier.  You have been
                    /// warned.
                    /// ---------------------------------------------------------------

                    if (mode == OrderMode.EXCEPTIONMOD_MODE)
                    {
                        if (MainMenuButton_155_58.SelectedProductGroup.EXCEPTION_MODIFIER_GROUPS.Count != 0)
                        {
                            OrderApi.CustomerTicketListView.IsHitTestVisible = false;
                            _currentFormMode = mode;

                            ///Save the previous pivot index for when we drop back to non-modify mode.
                            _previouslySelectedMainPivotIndex = _mainPivotIndex;

                            ///Make sure the the scroll pivots are reset.
                            ResetMenuPivotIndices();
                            SetMainCatDataContext();
                            _selectedExceptionModifierGroup = _exceptionModifierGroupsList[0];
                            SetSubCatDataContext();

                            Button_95_50 b = null;

                            if (Constants.IsQuickServiceMode)
                            {
                                b = Oceanside.OrderApi.PanelAuxFunctions.Children[4] as Button_95_50;
                            }
                            else
                            {
                                b = Oceanside.OrderApi.PanelTopFunctions.Children[8] as Button_95_50;
                            }

                            Button_95_50 bNo = Oceanside.OrderApi.PanelAuxFunctions.Children[2] as Button_95_50;
                            Button_95_50 bExtra = Oceanside.OrderApi.PanelAuxFunctions.Children[3] as Button_95_50;
                            Button_95_50 bSide = Oceanside.OrderApi.PanelAuxFunctions.Children[4] as Button_95_50;

                            ///This will assure that the first button in the main cat (modify in this case) is highlighted.
                            _buttonEightOriginalText = b.ButtonLabelText;
                            _buttonAux2_OriginalText = bNo.ButtonLabelText;
                            _buttonAux3_OriginalText = bExtra.ButtonLabelText;
                            _buttonAux4_OriginalText = bSide.ButtonLabelText;

                            b.ButtonLabelText = "Exit Modify";
                            b.ButtonBackground = _modifierHotKeysBrush;

                            bNo.ButtonLabelText = "With Out";
                            bNo.ButtonBackground = _exitModifierModeTextBrush;

                            bExtra.ButtonLabelText = "Extra";
                            bExtra.ButtonBackground = _exitModifierModeTextBrush;

                            bSide.ButtonLabelText = "Side of";
                            bSide.ButtonBackground = _exitModifierModeTextBrush;

                            _mainCategoryButtonsList[0].HighlightNew();
                        }
                    }
                    else
                    {
                        OrderApi.CustomerTicketListView.IsHitTestVisible = false;

                        _currentFormMode = mode;

                        ///Save the previous pivot index for when we drop back to non-modify mode.
                        _previouslySelectedMainPivotIndex = _mainPivotIndex;

                        ///Make sure the the scroll pivots are reset.
                        ResetMenuPivotIndices();
                        SetMainCatDataContext();

                        _selectedForcedModifierGroup = _forcedModifierGroupsList[0];

                        SetSubCatDataContext();

                        Button_95_50 b = null;

                        if (Constants.IsQuickServiceMode)
                        {
                            b = Oceanside.OrderApi.PanelAuxFunctions.Children[4] as Button_95_50;
                        }
                        else
                        {
                            b = Oceanside.OrderApi.PanelTopFunctions.Children[8] as Button_95_50;
                        }



                        ///Make the forced modify message box visible.
                        Oceanside.OrderApi.GridModifyMessage.Visibility = Visibility.Visible;

                        ///This will assure that the first button in the main cat (modify in this case) is highlighted.
                        _buttonEightOriginalText = b.ButtonLabelText;
                        b.ButtonLabelText = "Exit Modify";
                        b.ButtonBackground = _modifierHotKeysBrush;
                        _mainCategoryButtonsList[0].HighlightNew();
                    }


                    ///----------------------------------------------------------------
                    /// CAUTION: See the cautionary notes at the top of this function.
                    /// ---------------------------------------------------------------
                }
            }
        }


        /// <summary>
        /// 
        /// </summary>
        static public void DropOutOfModifyMode()
        {
            OrderApi.CustomerTicketListView.IsHitTestVisible = true;
            Oceanside.OrderApi.TbModifyMessage.Text = "";
            _exceptionModPrinterNote = "";

            Button_95_50 bExitMod = null;
            if (Constants.IsQuickServiceMode)
            {
                bExitMod = Oceanside.OrderApi.PanelAuxFunctions.Children[4] as Button_95_50;
            }
            else
            {
                bExitMod = Oceanside.OrderApi.PanelTopFunctions.Children[8] as Button_95_50;
            }

            bExitMod.ButtonLabelText = _buttonEightOriginalText;
            bExitMod.ButtonBackground = _normalModifierTextBrush;

            if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
            {
                Button_95_50 bNo = Oceanside.OrderApi.PanelAuxFunctions.Children[2] as Button_95_50;
                Button_95_50 bExtra = Oceanside.OrderApi.PanelAuxFunctions.Children[3] as Button_95_50;
                Button_95_50 bSide = Oceanside.OrderApi.PanelAuxFunctions.Children[4] as Button_95_50;

                bNo.ButtonLabelText = _buttonAux2_OriginalText;
                bNo.ButtonBackground = _normalModifierTextBrush;

                bExtra.ButtonLabelText = _buttonAux3_OriginalText;
                bExtra.ButtonBackground = _normalModifierTextBrush;

                bSide.ButtonLabelText = _buttonAux4_OriginalText;
                bSide.ButtonBackground = _normalModifierTextBrush;
            }

            _currentFormMode = OrderMode.PRODUCT_MODE;
            Oceanside.OrderApi.GridModifyMessage.Visibility = Visibility.Hidden;

            _mainCategoryButtonsList[0].HighlightPrevious();

            ///Set the pivot index back to where it was.
            _mainPivotIndex = _previouslySelectedMainPivotIndex;

            if (_selectedProduct != null)
            {
                foreach (FORCED_MODIFIER_GROUP fmg in _selectedProduct.FORCED_MODIFIER_GROUPS)
                {
                    fmg.ForceCount = 0;
                }
            }

            ///Make sure the the scroll pivots are reset.
            _subPivotIndex = 0; ///Only reset the sub menu index because we are going to reselect the previously selected main menu item.
            SetMainCatDataContext();
            SetSubCatDataContext();

            if (Constants.IsQuickServiceMode)
            {
                CCBindings.SelectedSeatIndex = 0;
                OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                OrderApi.CustomerCheckListView.Items.Refresh();
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
            }
        }


        public static void NewSeatClicked()
        {
            SHIFT.SelectedOrder.GuestCount += 1;

            if (SHIFT.SelectedOrder.SplitBySeatHasBeenApplied == true)
            {
                SHIFT.SelectedOrder.CheckCount += 1;
            }
            int seatCount = SHIFT.SelectedOrder.GuestCount;
            if (seatCount > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
            {
                _seatPivotIndex = seatCount - Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA;
            }

            ///Update the currently displayed seat to the new one just added.
            SeatChangeOccured(seatCount - 1);

            ///Assure the scrollable seat buttons display correctly now that we have added a new
            ///seat.
            SetScrollableSeatButtonsDataContext();
            SetSeatTags(_seatPivotIndex);
        }


        /// <summary>
        /// A databound function that is bound at startupand handles clicks when 
        /// the user presses the delete button.
        /// </summary>
        public static void DeleteUnRelayedProduct(SALE sale, bool askFirst = true)
        {
            bool shouldDelete = true;
            if (sale != null && !sale.IsForcedProduct)
            {
                if (CanModifyProduct(sale))
                {
                    if (askFirst)
                    {
                        YesNoBox mb = new YesNoBox();
                        mb.SetMessage("Are you sure you want to delete the selected product?");
                        mb.ShowDialog();

                        shouldDelete = YesNoBox.LastResponse == UserResponse.YES;
                    }

                    if (shouldDelete)
                    {
                        if (_currentFormMode != OrderMode.PRODUCT_MODE)
                        {
                            DropOutOfModifyMode();
                        }


                        sale.TryDeleteSinglePendingSale();

                        ///Now that the item has been removed, we need to update the selected index.
                        ///Place the index at one less than the previously selected index.
                        _custTicketScrollIndex = OrderApi.CustomerTicketListView.Items.Count - 1;
                        if (_custTicketScrollIndex < 0) ///Don't go below zero.
                        {
                            _custTicketScrollIndex = 0;
                        }
                        UpdateTicketFocus();
                        ///Must refresh because updating a quantity does not change the listview.
                        PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
                    }

                }
            }
        }

        /// <summary>
        /// A databound function that is bound at startupand handles clicks when 
        /// the user presses the delete button.
        /// </summary>
        public static void ClearClicked()
        {
            YesNoBox mb = new YesNoBox();
            mb.SetMessage("Are you sure you want to clear all products at seat #" + (SelectedSeatIndex + 1) +
                " that have not been submitted for order?");
            mb.ShowDialog();

            if (YesNoBox.LastResponse == UserResponse.YES)
            {
                //Clear all products at the current seat that have not been placed for order.  Leave out the forced and exception
                //mods because they will be deleted along wiht the product.
                foreach (SALE product in SHIFT.SelectedOrder.SALES.
                    Where(s => !s.IsExceptionModifier && !s.IsForcedModifier && s.OwningSeatNumber == SelectedSeatIndex).ToList())
                {
                    product.TryDeleteAllCountPendingSale();
                }
                UpdateTicketFocus(true);
                ///Must refresh because updating a quantity does not change the listview.
                if (Constants.IsQuickServiceMode)
                {
                    CCBindings.SelectedSeatIndex = 0;
                    OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                    OrderApi.CustomerCheckListView.Items.Refresh();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
            }
        }

        /// <summary>
        /// Scrolls the customers ticket up and down.
        /// </summary>
        /// <param Name="directionUp"></param>
        public static void TicketScrollClicked(bool directionUp)
        {
            if (directionUp)
            {
                _custTicketScrollIndex -= Constants.CONST_LINE_ITEMS_PER_CHECK_WINDOW_VIEW;

                ///Since we just went ahead and knocked off an entire view panels worth, we
                ///need to assure we didn't drive negative.
                if (_custTicketScrollIndex < 0)
                {
                    _custTicketScrollIndex = 0;
                }
            }
            else  ///Must be scroll down
            {
                _custTicketScrollIndex += Constants.CONST_LINE_ITEMS_PER_CHECK_WINDOW_VIEW;

                ///Make sure we didn't go too far, correct if we did by placing the view 
                ///at the end.
                IEnumerable<SALE> seatsSales = null;
                SHIFT.SelectedOrder.GetSeatsSales(SelectedSeatIndex);

                if (seatsSales != null && _custTicketScrollIndex >= seatsSales.Count())
                {
                    _custTicketScrollIndex = seatsSales.Count() - 1;
                }
            }
            UpdateTicketFocus();
        }

        /// <summary>
        /// 
        /// </summary>
        public static bool CheckExitMod()
        {
            bool wasInMod = true;
            if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
            {
                foreach (FORCED_MODIFIER_GROUP fmg in _selectedProduct.FORCED_MODIFIER_GROUPS)
                {
                    fmg.ForceCount = 0;
                }
                DropOutOfModifyMode();
            }
            else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
            {
                DropOutOfModifyMode();
            }
            else
            {
                wasInMod = false;
            }
            return wasInMod;
        }

        /// <summary>
        /// Will repeat the last ordered EfProductObject.
        /// </summary>
        public static void RepeatProduct()
        {
            if (_selectedSale != null && !_selectedSale.IsGiftCardSale)
            {
                bool updateIndex = false;
                SALE likeSale = null;

                if (_selectedSale.MODSALES.Count != 0)
                {
                    likeSale = _selectedSale;
                }
                else
                {
                    SALE.GetLikeProductSale(out likeSale,
                        SHIFT.SelectedOrder,
                        _selectedProduct,
                        _selectedSale.ProductsMainCatId,
                        SelectedSeatIndex,
                        _selectedSale.OwningCheckNumber);
                }
                if (likeSale != null)
                {
                    _selectedSale = likeSale;
                    _selectedSale.CountOrdered++;
                    _selectedSale.CountPendingKitchenSend++;
                    _selectedSale.LastOrderedDateTime = DateTime.Now;
                    foreach (SALE s in _selectedSale.MODSALES)
                    {
                        s.CountOrdered++;
                        s.CountPendingKitchenSend++;
                        s.LastOrderedDateTime = DateTime.Now;
                    }
                    _custTicketScrollIndex = OrderApi.CustomerTicketListView.Items.IndexOf(_selectedSale);
                }
                else
                {
                    PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();
                    PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == _selectedSale.ProductId).FirstOrDefault();
                    SALE sale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                    _selectedSale = sale;
                    updateIndex = true;
                }
                if (Constants.IsQuickServiceMode)
                {
                    CCBindings.SelectedSeatIndex = 0;
                    OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                    OrderApi.CustomerCheckListView.Items.Refresh();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
                UpdateTicketFocus(updateIndex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void AsAppetizerClicked()
        {
            SALE likeSale = Oceanside.OrderApi.CustomerTicketListView.SelectedItem as SALE;
            bool shouldUpdateIndx = false;
            if (likeSale != null)
            {
                if (CanModifyProduct(likeSale))
                {
                    if (_currentFormMode != OrderMode.EXCEPTIONMOD_MODE)
                    {
                        if (likeSale.NoteForPrint != null && likeSale.NoteForPrint.Equals("APP"))
                        {
                            likeSale.NoteForPrint = "";
                        }
                        else
                        {
                            if (likeSale.CountOrdered > 1)
                            {
                                PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == likeSale.ProductsMainCatId).FirstOrDefault();
                                PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == likeSale.ProductId).FirstOrDefault();
                                SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                                likeSale.CountOrdered--;
                                likeSale.CountPendingKitchenSend--;

                                newSale.NoteForPrint = "APP";
                                shouldUpdateIndx = true;
                            }
                            else
                            {
                                likeSale.NoteForPrint = "APP";
                            }
                        }
                    }
                    else
                    {
                        _exceptionModPrinterNote = "W/O";
                    }

                    UpdateTicketFocus(shouldUpdateIndx);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void TakeOutClicked()
        {
            SALE likeSale = Oceanside.OrderApi.CustomerTicketListView.SelectedItem as SALE;
            bool shouldUpdateIndx = false;
            if (likeSale != null)
            {
                if (CanModifyProduct(likeSale))
                {
                    if (likeSale.NoteForPrint != null && likeSale.NoteForPrint.Equals("TKO"))
                    {
                        likeSale.NoteForPrint = "";
                        likeSale.Ordermode = "INHOUSE";
                    }
                    else
                    {
                        if (likeSale.CountOrdered > 1)
                        {
                            PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == likeSale.ProductsMainCatId).FirstOrDefault();
                            PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == likeSale.ProductId).FirstOrDefault();
                            SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                            likeSale.CountOrdered--;
                            likeSale.CountPendingKitchenSend--;

                            newSale.NoteForPrint = "TKO";
                            newSale.Ordermode = "TAKEOUT";
                            shouldUpdateIndx = true;
                        }
                        else
                        {
                            likeSale.NoteForPrint = "TKO";
                            likeSale.Ordermode = "TAKEOUT";
                        }
                    }
                    UpdateTicketFocus(shouldUpdateIndx);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void DeliveryClicked()
        {
            SALE likeSale = Oceanside.OrderApi.CustomerTicketListView.SelectedItem as SALE;
            bool shouldUpdateIndx = false;
            if (likeSale != null)
            {
                if (CanModifyProduct(likeSale))
                {
                    if (likeSale.NoteForPrint != null && likeSale.NoteForPrint.Equals("DLV"))
                    {
                        likeSale.NoteForPrint = "";
                        likeSale.Ordermode = "INHOUSE";
                    }
                    else
                    {
                        if (likeSale.CountOrdered > 1)
                        {
                            PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == likeSale.ProductsMainCatId).FirstOrDefault();
                            PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == likeSale.ProductId).FirstOrDefault();
                            SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                            likeSale.CountOrdered--;
                            likeSale.CountPendingKitchenSend--;

                            newSale.NoteForPrint = "DLV";
                            newSale.Ordermode = "DELIVERY";
                            shouldUpdateIndx = true;
                        }
                        else
                        {
                            likeSale.NoteForPrint = "DLV";
                            likeSale.Ordermode = "DELIVERY";
                        }
                    }
                    UpdateTicketFocus(shouldUpdateIndx);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void DontMakeClicked()
        {
            SALE likeSale = Oceanside.OrderApi.CustomerTicketListView.SelectedItem as SALE;
            bool shouldUpdateIndx = false;
            if (likeSale != null)
            {
                if (CanModifyProduct(likeSale))
                {
                    if (_currentFormMode != OrderMode.EXCEPTIONMOD_MODE)
                    {
                        if (likeSale.NoteForPrint != null && likeSale.NoteForPrint.Equals("DTM"))
                        {
                            likeSale.NoteForPrint = "";
                        }
                        else
                        {
                            if (likeSale.CountOrdered > 1)
                            {
                                PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == likeSale.ProductsMainCatId).FirstOrDefault();
                                PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == likeSale.ProductId).FirstOrDefault();
                                SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                                likeSale.CountOrdered--;
                                likeSale.CountPendingKitchenSend--;

                                newSale.NoteForPrint = "DTM";
                                shouldUpdateIndx = true;
                            }
                            else
                            {
                                likeSale.NoteForPrint = "DTM";
                            }
                        }
                    }
                    else
                    {
                        _exceptionModPrinterNote = "EXT";
                    }
                    UpdateTicketFocus(shouldUpdateIndx);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void HoldClicked()
        {
            bool shouldUpdateIndx = false;
            SALE likeSale = Oceanside.OrderApi.CustomerTicketListView.SelectedItem as SALE;
            if (CanModifyProduct(likeSale))
            {
                if (likeSale != null)
                {
                    if (_currentFormMode != OrderMode.EXCEPTIONMOD_MODE)
                    {
                        ///Toggle the current hold to not hold or vise versa.
                        if (likeSale.OnHold == true)
                        {
                            likeSale.OnHold = false;
                            foreach (SALE s in likeSale.MODSALES)
                            {
                                s.NoteForPrint = "";
                                s.OnHold = false;
                            }


                            if (likeSale.NoteForPrintBeforeHold != null && likeSale.NoteForPrintBeforeHold.Equals("HLD"))
                            {
                                likeSale.NoteForPrint = "";
                            }
                            else
                            {
                                likeSale.NoteForPrint = likeSale.NoteForPrintBeforeHold;
                            }
                        }
                        else
                        {
                            if (likeSale.CountOrdered > 1)
                            {
                                PRODUCT_GROUP pg =
                                    SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == likeSale.ProductsMainCatId).FirstOrDefault();
                                PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == likeSale.ProductId).FirstOrDefault();
                                SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                                likeSale.CountOrdered--;
                                likeSale.CountPendingKitchenSend--;

                                newSale.NoteForPrint = "HLD";
                                newSale.OnHold = true;
                                foreach (SALE s in newSale.MODSALES)
                                {
                                    s.OnHold = true;
                                }

                                shouldUpdateIndx = true;
                            }
                            else
                            {
                                likeSale.OnHold = true;
                                foreach (SALE s in likeSale.MODSALES)
                                {
                                    s.OnHold = true;
                                }

                                likeSale.NoteForPrintBeforeHold = likeSale.NoteForPrint;
                                likeSale.NoteForPrint = "HLD";
                            }
                        }

                        ///Now see if the order itself still needs to blink.
                        SHIFT.SelectedOrder.HasProductsOnHold = false;
                        foreach (SALE s in SHIFT.SelectedOrder.SALES)
                        {
                            if (s.OnHold)
                            {
                                SHIFT.SelectedOrder.HasProductsOnHold = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        _exceptionModPrinterNote = "SDE";
                    }
                    UpdateTicketFocus(shouldUpdateIndx);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void SubmitOrderClicked()
        {
            if (_currentFormMode != OrderMode.PRODUCT_MODE)
            {
                DropOutOfModifyMode();
            }

            PrintSpool.PrintDispatchedReceipt(SHIFT.SelectedOrder);

            foreach (SALE sale in SHIFT.SelectedOrder.SALES)
            {
                if (!sale.OnHold)
                {
                    sale.CountPendingKitchenSend = 0;
                }
            }
            if (Constants.IsQuickServiceMode)
            {
                CCBindings.SelectedSeatIndex = 0;
                OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                OrderApi.CustomerCheckListView.Items.Refresh();
            }
            PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
            UpdateTicketFocus();
            SHIFT.GlobalContext.SaveChanges();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static bool IsPendingAction(bool showMessage = true)
        {
            bool retValue = false;
            try
            {
                if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
                {
                    retValue = true;
                    if (showMessage)
                    {
                        UMD.ShowGuiMessageSTASafe_NOTHROW("Please finish selecting this product's modifiers.");
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.LogException(ex);
            }
            return retValue;
        }

        /// <summary>
        /// 
        /// </summary>
        public static void LockClicked()
        {
            ///Submit orders and jump to login page.
            SubmitOrderClicked();

            if (Constants.IsQuickServiceMode)
            {
                PosWindow.WindowBeforeLock = QuickOrderWindow.Singleton;
            }
            Oceanside.LoginWindow.Show();
        }


        public static HowManyBox HowManyBoxToClose;
        ///<summary>
        /// This function is called by the how many window when the user clicks the howmany button to see the numberic keypad
        /// and enters an integer obj.
        /// </summary>
        public static void RepeatLastProduct_x_Times_NOTHROW(int numTimes)
        {
            try
            {
                HowManyBoxToClose.Close();
                if (numTimes != 0 && _selectedSale != null)
                {
                    bool updateIndex = false;

                    SALE likeSale = null;


                    if (_selectedSale.MODSALES.Count != 0)
                    {
                        likeSale = _selectedSale;
                    }
                    else
                    {
                        SALE.GetLikeProductSale(out likeSale, SHIFT.SelectedOrder,
                            _selectedProduct,
                            _selectedSale.ProductsMainCatId,
                            SelectedSeatIndex,
                            _selectedSale.OwningCheckNumber);
                    }
                    if (likeSale != null)
                    {
                        _selectedSale = likeSale;
                        _selectedSale.CountOrdered += numTimes;
                        _selectedSale.CountPendingKitchenSend += numTimes;
                        _selectedSale.LastOrderedDateTime = DateTime.Now;

                        foreach (SALE s in _selectedSale.MODSALES)
                        {
                            s.CountOrdered++;
                            s.CountPendingKitchenSend++;
                            s.LastOrderedDateTime = DateTime.Now;
                        }

                        _custTicketScrollIndex = OrderApi.CustomerTicketListView.Items.IndexOf(_selectedSale);
                    }
                    else
                    {
                        PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();
                        PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == _selectedSale.ProductId).FirstOrDefault();
                        _selectedSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                        _selectedSale.CountOrdered = numTimes;
                        _selectedSale.CountPendingKitchenSend = numTimes;
                        updateIndex = true;
                    }
                    if (Constants.IsQuickServiceMode)
                    {
                        CCBindings.SelectedSeatIndex = 0;
                        OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                        OrderApi.CustomerCheckListView.Items.Refresh();
                    }
                    PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
                    UpdateTicketFocus(updateIndex);
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_REPEAT_PROD_CLICK, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void ExceptionModify(bool isSeeServerMode = false)
        {
            if (_selectedSale != null)
            {
                if (isSeeServerMode)
                {
                    HandleSeeServerRequest();
                }
                else
                {
                    DropIntoModifyMode(OrderMode.EXCEPTIONMOD_MODE);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void HandleSeeServerRequest()
        {
            Oceanside.FullKeyboard.ActiveKeyboard.SetSmallMode(false);
            Oceanside.FullKeyboard.ActiveKeyboard.SetMessage("Enter Modifier:");
            Oceanside.FullKeyboard.ActiveKeyboard.ShowMe();

            if (Oceanside.FullKeyboard.LastResponse == UserResponse.ENTER && _selectedSale != null)
            {
                bool updateTicketFocus = false;

                if (_selectedSale.CountOrdered > 1)
                {
                    PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();
                    PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == _selectedSale.ProductId).FirstOrDefault();
                    SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                    _selectedSale.CountOrdered--;
                    _selectedSale.CountPendingKitchenSend--;
                    updateTicketFocus = true;
                    _selectedSale = newSale;
                }

                SALE seeServerSale = new SALE();
                seeServerSale.RevenueTypeId = 0;
                seeServerSale.ProductName = Oceanside.FullKeyboard.GuiKeyPressedString;
                seeServerSale.CountOrdered = 1;
                seeServerSale.CountPendingKitchenSend = 1;
                seeServerSale.CountsAsSalesRevenue = false;
                seeServerSale.IsExceptionModifier = true;
                seeServerSale.IsForcedModifier = false;
                seeServerSale.MenuPrice = 0M;
                seeServerSale.ActualPrice = 0M;
                seeServerSale.OnHold = false;
                seeServerSale.FirstOrderedDateTime = DateTime.Now;
                seeServerSale.LastOrderedDateTime = seeServerSale.FirstOrderedDateTime;
                seeServerSale.OwningSeatNumber = SelectedSeatIndex;
                if (SHIFT.SelectedOrder.SplitBySeatHasBeenApplied == true)
                {
                    seeServerSale.OwningCheckNumber = _selectedSeatIndex;

                    if (_selectedSeatIndex >= SHIFT.SelectedOrder.CheckCount)
                    {
                        SHIFT.SelectedOrder.CheckCount++;
                    }
                }
                else
                {
                    seeServerSale.OwningCheckNumber = 0;
                }
                seeServerSale.PARENTSALE_WHEN_MODSALE = _selectedSale;
                seeServerSale.PrinterGroupingId = _selectedProduct.ProductGroupPrinterId;
                seeServerSale.ProductId = _selectedProduct.Id;
                seeServerSale.ProductName = Oceanside.FullKeyboard.GuiKeyPressedString;
                seeServerSale.ProductsMainCatId = MainMenuButton_155_58.SelectedProductGroup.Id;
                seeServerSale.RevenueCenterId = KIOSK.Get(SHIFT.GlobalContext).RevenueCenterId;
                seeServerSale.UserId = SHIFT.Current.User.Id;
                seeServerSale.WasVoided = false;
                seeServerSale.IsSeeServer = true;
                seeServerSale.PARENTSALE_WHEN_MODSALE = _selectedSale;

                SALE.InsertNewSeatSequenceSale(seeServerSale, _selectedSale.SeatSequenceNumber + 1, SelectedSeatIndex);
                SALE.InsertNewCheckSequenceSale(seeServerSale, _selectedSale.CheckSequenceNumber + 1, _selectedSale.OwningCheckNumber);
                _selectedSale = seeServerSale;
                SHIFT.SelectedOrder.SALES.Add(seeServerSale);
                seeServerSale.ORDER = SHIFT.SelectedOrder;

                UpdateTicketFocus(updateTicketFocus);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void NewTableClicked()
        {
            ///This function can serve to also cancel the modifier mode when the minimum amount of modifiers have
            ///been added.
            if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
            {
                //selectedProduct.ResetForceCount();
                DropOutOfModifyMode();
            }
            else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE)
            {
                DropOutOfModifyMode();
            }
            else  ///If we are not in modifier mode then the asapp button was really clicked
            {
                if (!IsPendingAction())
                {
                    SubmitOrderClicked();
                    NTBindings.IsBarSeatMode = false;
                    Oceanside.NewTableWindow.Show();
                }
            }
        }

        /// <summary>
        /// Called when a submenu or submodifier item is clicked
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSubMenu_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;

            try
            {
                if (SHIFT.SelectedOrder.IsClosed)
                {
                    UMD.ShowGuiMessageSTASafe_NOTHROW("This order has already been closed, please use an open order.");
                }
                else
                {
                    if (CurrentFormMode != OrderMode.FORCEDMOD_MODE)
                    {
                        Oceanside.OrderApi.GridModifyMessage.Visibility = Visibility.Hidden;
                    }

                    string indxString = (string)((Oceanside.FlatButton_155_58)e.OriginalSource).Tag;
                    int selectedIndex = Convert.ToInt32(indxString);

                    if (_currentFormMode == OrderMode.FORCEDMOD_MODE && _selectedSale != null)
                    {
                        ///Super fast fingers can actually cause events to happen out of order.  Just
                        ///return and let them hit it a second time.
                        if (_forcedModifiersForForcedGroupList == null)
                        {
                            Logging.LogMessage("Submenu Clicked but the _forcedModifiersForForcedGroupList was null");
                            return;
                        }

                        if (selectedIndex >= _forcedModifiersForForcedGroupList.Length)
                        {
                            Logging.LogMessage("Submenu Clicked but the selectedIndex is greater than the _forcedModifiersForForcedGroupList.Length");
                            return;
                        }

                        _selectedForcedModifier = _forcedModifiersForForcedGroupList[selectedIndex];

                        ///CAUTION: Notice that I am updating the forced modifier group
                        ///from the products array of forced modifier groups and not the
                        ///selected group itself.  They are two different object references
                        ///because of the detached state of the menu in relationship to the 
                        ///database and EntityFramework.
                        if (_selectedForcedModifierGroup == null)
                        {
                            Logging.LogMessage("Submenu Clicked but the _selectedForcedModifierGroup was null");
                            return;
                        }

                        if (_selectedProduct == null)
                        {
                            Logging.LogMessage("Submenu Clicked but the _selectedProduct was null");
                            return;
                        }

                        _selectedForcedModifierGroup =
                            _selectedProduct.FORCED_MODIFIER_GROUPS.Where(f => f.Id == _selectedForcedModifierGroup.Id).FirstOrDefault();

                        ///END OF CAUTION:  You have been warned.
                        if (_selectedForcedModifierGroup.ForceCount < _selectedForcedModifierGroup.MaximumChoice)
                        {
                            _selectedForcedModifierGroup.ForceCount++;

                            SALE sale = SALE.AddForcedModSale(_selectedForcedModifierGroup,
                                _selectedForcedModifier,
                                _selectedSale,
                                SelectedSeatIndex,
                                MainMenuButton_155_58.SelectedProductGroup.CanDiscountGroup);

                            bool allModsAreAdded = true;


                            ///See if the forced mods have been added.
                            foreach (FORCED_MODIFIER_GROUP fmg in
                                _selectedProduct.FORCED_MODIFIER_GROUPS.OrderBy(f => f.Id).OrderBy(g => g.Name))
                            {
                                if (fmg.ForceCount < fmg.MaximumChoice)
                                {
                                    allModsAreAdded = false;
                                    break;
                                }
                            }

                            ///If they have been added, then clear them all and drop out of forced mode.
                            if (allModsAreAdded)
                            {
                                _selectedForcedModifierGroup.ForceCount = 0;
                                foreach (FORCED_MODIFIER_GROUP fmg in _selectedProduct.FORCED_MODIFIER_GROUPS)
                                {
                                    fmg.ForceCount = 0;
                                }
                                DropOutOfModifyMode();
                            }
                            else
                            {
                                Oceanside.OrderApi.TbModifyMessage.Text = _selectedProduct.GetModifierChoiceInstruction(_selectedForcedModifierGroup);

                                if (_selectedForcedModifierGroup.ForceCount >= _selectedForcedModifierGroup.MaximumChoice)
                                {
                                    ///Move to the next mod group that needs to be selected.
                                    int index = 0;
                                    FORCED_MODIFIER_GROUP[] listOfForcedMods = MENU.GetAllForcedModifierGroups(_selectedProduct);
                                    foreach (FORCED_MODIFIER_GROUP fmg in listOfForcedMods)
                                    {
                                        if (fmg.ForceCount < fmg.MaximumChoice)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            index++;
                                        }
                                    }
                                    MainMenuButtonClicked(index);
                                    SetSubCatDataContext();
                                    _mainCategoryButtonsList[index].HighlightNew();
                                }
                            }
                            UpdateTicketFocus(false);
                        }
                        else
                        {
                            UMD.ShowGuiMessageSTASafe_NOTHROW("You have reached the maximum choice for the forced modifier group " +
                                _selectedForcedModifierGroup.Name + ".");
                        }
                    }
                    else if (_currentFormMode == OrderMode.EXCEPTIONMOD_MODE && _selectedSale != null)
                    {
                        ///Super fast fingers can actually cause events to happen out of order.  Just
                        ///return and let them hit it a second time.
                        if (selectedIndex >= _exceptionModifiersForExceptionGroupList.Length)
                        {
                            Logging.LogMessage("The selectedIndex is >= _exceptionMofidiersForExceptionGroupList.Length");
                            return;
                        }
                        _selectedExceptionModifier = _exceptionModifiersForExceptionGroupList[selectedIndex];

                        ///TODO
                        bool isWithout = (_exceptionModPrinterNote != null && _exceptionModPrinterNote.Equals("W/O"));
                        ///If we are applying an exception mod to a product that has been ordered more than one time, we
                        ///need to pull it off the list and put it on a separate line item.
                        if (_selectedSale.CountOrdered > 1)
                        {
                            PRODUCT_GROUP pg = SHIFT.GlobalContext.PRODUCT_GROUPS.Where(p => p.Id == _selectedSale.ProductsMainCatId).FirstOrDefault();
                            PRODUCT product = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == _selectedSale.ProductId).FirstOrDefault();
                            SALE newSale = SALE.AddProductSale(pg, product, SelectedSeatIndex, false);
                            _selectedSale.CountOrdered--;
                            _selectedSale.CountPendingKitchenSend--;
                            UpdateTicketFocus(true);
                        }

                        ///Create a new sale for the modifier.
                        SALE sale = SALE.AddExceptionModSale(_selectedExceptionModifierGroup,
                            _selectedExceptionModifier,
                            _selectedSale,
                            SelectedSeatIndex,
                            MainMenuButton_155_58.SelectedProductGroup.CanDiscountGroup);
                        sale.NoteForPrint = _exceptionModPrinterNote;
                        sale.IsWithout = isWithout;

                        if (isWithout)
                        {
                            sale.ActualPrice = 0M;
                        }

                        _exceptionModPrinterNote = "";
                        UpdateTicketFocus(false);
                    }
                    else
                    {
                        OrderProduct(selectedIndex);
                    }

                    if (Constants.IsQuickServiceMode && Constants.HasCfd)
                    {
                        decimal amountDue = SHIFT.SelectedOrder.CheckUnpaidGrandTotal(0);
                        System.Threading.Tasks.Task.Factory.StartNew(() => CFD.WriteAmount(amountDue, false));
                    }
                }
            }
            catch (Exception exc)
            {
                ///This is a bunch of temp debug code that is used to find an anomoly that does not
                ///occur very often.  Once in a while an exception is thrown from this function.
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SUBMENU_BUTTON_CLICK, exc);
            }
        }

        public static void OrderProduct(int selectedIndex, Button_95_50 b = null)
        {
            try
            {
                if (CurrentFormMode != OrderMode.FORCEDMOD_MODE)
                {
                    Oceanside.OrderApi.GridModifyMessage.Visibility = Visibility.Hidden;
                }

                bool makeLastItemNewIndx = true;
                bool canAddProduct = true;

                if (b == null)
                {
                    MainMenuButton_155_58.SelectedProductGroup = MainMenuButton_155_58.CurrentlySelected.DataContext as PRODUCT_GROUP;
                    ///Super fast fingers can actually cause events to happen out of order.  Just
                    ///return and let them hit it a second time.
                    if (MainMenuButton_155_58.SelectedProductGroup == null || selectedIndex >= _productsForProductGroupList.Length)
                    {
                        Logging.LogMessage("_selectedProductGroup == null || selectedIndex >= _productsForProductGroupList.Length");
                        return;
                    }

                    _selectedProduct = _productsForProductGroupList[selectedIndex];

                }
                else
                {
                    MainMenuButton_155_58.SelectedProductGroup =
                        SHIFT.GlobalContext.PRODUCT_GROUPS.Where(pg => pg.Id == b.ProductGroupId).FirstOrDefault();

                    ///Super fast fingers can actually cause events to happen out of order.  Just
                    ///return and let them hit it a second time.
                    if (MainMenuButton_155_58.SelectedProductGroup == null)
                    {
                        Logging.LogMessage("_selectedProductGroup == null");
                        return;
                    }
                    _selectedProduct = SHIFT.GlobalContext.PRODUCTS.Where(p => p.Id == b.ProductId).FirstOrDefault();

                }

                ///We need to make sure that if this is a daily special, we must debit the
                ///counter.
                if (_selectedProduct.RemoveAtZeroCount)
                {
                    if (_selectedProduct.Downtick > 0)
                    {
                        ///Update the remote object
                        _selectedProduct.Downtick--;
                    }
                    else
                    {
                        canAddProduct = false;
                        MessageBox mb = new MessageBox();
                        mb.SetMessage("This product is no longer available and will be removed from the menu.");
                        mb.ShowDialog();
                    }
                }
                if (canAddProduct)
                {
                    SALE likeSale = null;

                    SALE.GetLikeProductSale(out likeSale,
                        SHIFT.SelectedOrder,
                        _selectedProduct,
                        MainMenuButton_155_58.SelectedProductGroup.Id,
                        SelectedSeatIndex,
                        0);

                    if (_selectedProduct.FORCED_MODIFIER_GROUPS.Count != 0 || likeSale == null)
                    {
                        ///********************************
                        ///Caution: When adding a product sale that is a gift card sale, it will not return to this function
                        ///will anything but a null sale.  It is an asynch execution via the credit card processing gateway
                        ///needed to place a balance on the card.
                        SALE sale = SALE.AddProductSale(MainMenuButton_155_58.SelectedProductGroup, _selectedProduct, SelectedSeatIndex, false);
                        _selectedSale = sale;
                    }
                    else
                    {

                        makeLastItemNewIndx = false;
                        _selectedSale = likeSale;
                        _selectedSale.CountOrdered++;
                        _selectedSale.CountPendingKitchenSend++;
                        _selectedSale.LastOrderedDateTime = DateTime.Now;
                        _custTicketScrollIndex = OrderApi.CustomerTicketListView.Items.IndexOf(_selectedSale);

                        ///Must refresh because updating a quantity does not change the listview.
                        if (Constants.IsQuickServiceMode)
                        {
                            CCBindings.SelectedSeatIndex = 0;
                            OrderApi.CustomerCheckListView.ItemsSource = new List<ORDER> { SHIFT.SelectedOrder };
                            OrderApi.CustomerCheckListView.Items.Refresh();
                        }
                        PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.PO);
                    }


                    _forcedModifierGroupsList = MENU.GetAllForcedModifierGroups(_selectedProduct);

                    if (_forcedModifierGroupsList != null)
                    {
                        for (int idx = 0; idx < _forcedModifierGroupsList.Length; idx++)
                        {
                            if (_forcedModifierGroupsList[idx].MaximumChoice != 0)
                            {
                                DropIntoModifyMode(OrderMode.FORCEDMOD_MODE);
                                break;
                            }
                        }
                    }

                    if (_currentFormMode == OrderMode.FORCEDMOD_MODE)
                    {
                        Oceanside.OrderApi.TbModifyMessage.Text = _selectedProduct.GetModifierChoiceInstruction();
                    }
                }
                UpdateTicketFocus(makeLastItemNewIndx);

                if (b != null)
                {
                    if (Constants.IsQuickServiceMode && Constants.HasCfd)
                    {
                        decimal amountDue = SHIFT.SelectedOrder.CheckUnpaidGrandTotal(0);
                        System.Threading.Tasks.Task.Factory.StartNew(() => CFD.WriteAmount(amountDue, false));
                    }
                }
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SUBMENU_BUTTON_CLICK, exc);
            }
        }
    }
}
